// server/src/main.rs
use warp::Filter;
use sysinfo::{System, Networks, Disks};
use std::sync::{Arc, Mutex, OnceLock};
use std::time::{Duration, Instant};
use serde::Serialize;

// 全局系统资源监控
static NETWORKS: OnceLock<Mutex<Networks>> = OnceLock::new();
static DISKS: OnceLock<Mutex<Disks>> = OnceLock::new();

#[derive(Debug, Clone, Serialize)]
struct SystemInfo {
    cpu_model: String,
    gpu_model: String,
    ram: String,
    disk: String,
    speed: String,
    cpu_usage: f32,
    gpu_usage: f32,
    memory_usage: String,
    disk_usage: Vec<String>,
    network_speed: Vec<String>,
}

// 配置GUI路由
fn gui_route() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
    warp::path!("GUI")
        .map(|| {
            warp::reply::html(include_str!("../static/GUI.html"))
        })
}

// 获取硬件信息的工具函数
fn get_cpu_model() -> String {
    #[cfg(target_os = "linux")]
    {
        std::process::Command::new("sh")
            .args(["-c", "grep 'model name' /proc/cpuinfo | head -1 | cut -d':' -f2 | tr -d '\t'"])
            .output()
            .ok()
            .and_then(|o| String::from_utf8(o.stdout).ok())
            .unwrap_or_else(|| "Unknown CPU".into())
            .trim().to_string()
    }
    
    #[cfg(target_os = "windows")]
    {
        std::process::Command::new("wmic")
            .args(["cpu", "get", "name"])
            .output()
            .ok()
            .and_then(|o| String::from_utf8(o.stdout).ok())
            .map(|s| s.lines().nth(1).unwrap_or("").trim().to_string())
            .unwrap_or_else(|| "Unknown CPU".into())
    }
}

fn get_gpu_model() -> String {
    std::process::Command::new("nvidia-smi")
        .args(["--query-gpu=gpu_name", "--format=csv,noheader,nounits"])
        .output()
        .ok()
        .and_then(|o| String::from_utf8(o.stdout).ok())
        .unwrap_or_else(|| "Unknown GPU".into())
        .trim().to_string()
}

#[tokio::main]
async fn main() {
    // 初始化共享状态
    let sys_info = Arc::new(Mutex::new(SystemInfo {
        cpu_model: get_cpu_model(),
        gpu_model: get_gpu_model(),
        ram: String::new(),
        disk: String::new(),
        speed: "0 KB/s".into(),
        cpu_usage: 0.0,
        gpu_usage: 0.0,
        memory_usage: String::new(),
        disk_usage: Vec::new(),
        network_speed: Vec::new(),
    }));

    // 启动监控线程
    let monitor_info = sys_info.clone();
    std::thread::spawn(move || {
        let mut sys = System::new_all();
        let mut prev_net_rx = 0;
        let mut prev_net_tx = 0;
        let mut prev_time = Instant::now();

        NETWORKS.get_or_init(|| Mutex::new(Networks::new_with_refreshed_list()));
        DISKS.get_or_init(|| Mutex::new(Disks::new_with_refreshed_list()));

        loop {
            // 刷新系统信息
            sys.refresh_all();
            
            // 收集数据
            let cpu_usage = sys.global_cpu_usage();
            let total_ram = sys.total_memory() as f64 / 1e9;
            let used_ram = sys.used_memory() as f64 / 1e9;
            let gpu_usage = get_gpu_utilization().unwrap_or(0.0);

            // 处理磁盘信息
            let (disk_usage, main_disk) = DISKS.get().map(|disks| {
                let mut disks = disks.lock().unwrap();
                disks.refresh(true);
                let usage: Vec<_> = disks.list().iter().map(|d| {
                    format!("{}: {:.1} GB / {:.1} GB", 
                        d.name().to_string_lossy(),
                        d.available_space() as f64 / 1e9,
                        d.total_space() as f64 / 1e9)
                }).collect();
                (usage.clone(), usage.first().cloned().unwrap_or_default())
            }).unwrap_or_default();

            // 处理网络信息
            let mut network_speed = Vec::new();
            NETWORKS.get().map(|networks| {
                let mut networks = networks.lock().unwrap();
                networks.refresh(true);
                
                for (name, net) in networks.iter() {
                    if ["Ethernet", "Wi-Fi", "eth0","WLAN"].iter().any(|&n| name.contains(n)) {
                        let elapsed = prev_time.elapsed().as_secs_f64().max(0.1);
                        
                        let dl =(net.received().saturating_sub(prev_net_rx)) as f64 / elapsed;
                        let ul = (net.transmitted().saturating_sub(prev_net_tx)) as f64 / elapsed;
                        
                        let (dl_speed, dl_unit) = if dl >= 1_000_000.0 {
                            (dl / 1_000_000.0, "MB")
                        } else {
                            (dl / 1000.0, "KB")
                        };
                        
                        let (ul_speed, ul_unit) = if ul >= 1_000_000.0 {
                            (ul / 1_000_000.0, "MB")
                        } else {
                            (ul / 1000.0, "KB")
                        };
                        
                        network_speed.push(format!(
                            "{} ▼{:.1}{}/s ▲{:.1}{}/s",
                            name, dl_speed, dl_unit, ul_speed, ul_unit
                        ));
                        
                        prev_net_rx = net.received();
                        prev_net_tx = net.transmitted();
                    }
                }
            });

            // 更新共享状态
            let mut info = monitor_info.lock().unwrap();
            info.cpu_usage = cpu_usage as f32;
            info.gpu_usage = gpu_usage;
            info.ram = format!("{:.0} GB", total_ram);
            info.memory_usage = format!("{:.1} GB / {:.1} GB", used_ram, total_ram);
            info.disk = main_disk;
            info.disk_usage = disk_usage;
            info.network_speed = network_speed;

            prev_time = Instant::now();
            std::thread::sleep(Duration::from_secs(1));
        }
    });

    // 配置API路由
    let api_route = warp::path!("system-info")
        .map(move || {
            let data = sys_info.lock().unwrap();
            warp::reply::json(&*data)
        });

    // 配置API路由(GUI)
    // 组合路由
    let routes = api_route.or(gui_route());

    // 启动Web服务器
    println!("API服务已启动: http://localhost:8080/system-info");
    println!("监控面板已启动: http://localhost:8080/GUI");
    warp::serve(routes)
        .run(([0, 0, 0, 0], 8080))
        .await;
}

fn get_gpu_utilization() -> Option<f32> {
    std::process::Command::new("nvidia-smi")
        .args(["--query-gpu=utilization.gpu", "--format=csv,noheader,nounits"])
        .output()
        .ok()
        .and_then(|o| String::from_utf8(o.stdout).ok())
        .and_then(|s| s.trim().parse().ok())
}